// Create the classes needed to play the game
function Enum() {}

NUM_EDGES = 72;
NUM_VERTICES = 54;
DEBUG = false;
placing_settlement = false;
placing_city = false;
placing_road = false;
actions_enabled = false;

Enum.ResourceType = {0:"grain", 1:"sheep", 2:"forest", 3:"ore", 4:"brick", 5:"desert"}
Enum.BuildingType = {0:"Settlement", 1:"City"}
playerColors = {0:"red", 1:"orange", 2:"white", 3:"blue"}
var edge_to_vertext_map = {0: [0, 3], 1: [0, 4], 2: [1, 4], 3: [1, 5], 4: [2, 5], 5: [2, 6], 6: [3, 7], 7: [4, 8], 8: [5, 9], 9: [6, 10], 10: [7, 11], 11: [7, 12], 12: [8, 12], 13: [8, 13], 14: [9, 13], 15: [9, 14], 16: [10, 14], 17: [10, 15], 18: [11, 16], 19: [12, 17], 20: [13, 18], 21: [14, 19], 22: [15, 20], 23: [16, 21], 24: [16, 22], 25: [17, 22], 26: [17, 23], 27: [18, 23], 28: [18, 24], 29: [19, 24], 30: [19, 25], 31: [20, 25], 32: [20, 26], 33: [21, 27], 34: [22, 28], 35: [23, 29], 36: [24, 30], 37: [25, 31], 38: [26, 32], 39: [27, 33], 40: [28, 33], 41: [28, 34], 42: [29, 34], 43: [29, 35], 44: [30, 35], 45: [30, 36], 46: [31, 36], 47: [31, 37], 48: [32, 37], 49: [33, 38], 50: [34, 39], 51: [35, 40], 52: [36, 41], 53: [37, 42], 54: [38, 43], 55: [39, 43], 56: [39, 44], 57: [40, 44], 58: [40, 45], 59: [41, 45], 60: [41, 46], 61: [42, 46], 62: [43, 47], 63: [44, 48], 64: [45, 49], 65: [46, 50], 66: [47, 51], 67: [48, 51], 68: [48, 52], 69: [49, 52], 70: [49, 53], 71: [50, 53]};

function setVertexPoint(x, y, index) {
	webui_client.context.vertices[index].x = x;
	webui_client.context.vertices[index].y = y;
	if(DEBUG == true) {
		var dot = document.createElement('div');
		dot.setAttribute('class', 'dot');
		dot.setAttribute('style', 'top: '+y+'; left: '+x+';');	
		$('body').append(dot);
	}
}

function addToRow(div, row_div, row_num, order, index) {
	// Calculate the x,y of the hex, and add it to the DOM
	var row_counts = {1:3, 2:4, 3:5, 4:4, 5:3}
	var HEX_HEIGHT = 90;
	var HEX_WIDTH = 112;
	var MAX_ELEMS_IN_ROW = 5;
	var BORDER_WIDTH = 1;
	var Y_OFFSET = 30;
	var y = ((row_num-1) * HEX_HEIGHT) + (BORDER_WIDTH * row_num) + Y_OFFSET;
	var x = (((MAX_ELEMS_IN_ROW * HEX_WIDTH) - row_counts[row_num] * HEX_WIDTH) / 2) + (order * HEX_WIDTH) + (order * BORDER_WIDTH);
	div.setAttribute('style', 'top: '+y+'px; left: '+x+'px;');
	if(row_div) row_div.append(div);

	// Render the thief
	if(index == webui_client.context.thief_hex_id) {
		var game = $('#game');
		var img = document.createElement('img');
		img.setAttribute('style', 'top: '+(y+40)+'; left: '+(x+10)+';');
		img.setAttribute('class', 'overlay');
		img.setAttribute('src', "images/thief.png"); 
		img.setAttribute('width', '45px;');
		img.setAttribute('height', '45px;');
		game.append(img);	
	}

	// Add vertex coordinates to webui_client.context
	switch(row_num) {
		case 1:
			setVertexPoint(x+56, y+3, index);
			setVertexPoint(x+112, y+35, index+4);
			setVertexPoint(x+112, y+95, index+8);
			setVertexPoint(x+56, y+125, index+12);
			if(index == 0) { 
				setVertexPoint(x, y+95, index+7);
				setVertexPoint(x, y+35, index+3); 
			}
			break;
		case 2:
			setVertexPoint(x+112, y+35, index+9);
			setVertexPoint(x+112, y+95, index+14);
			setVertexPoint(x+56, y+125, index+19);
			if(index == 3) {
				setVertexPoint(x, y+95, index+13);
				setVertexPoint(x, y+35, index+8);
			}
			break;
		case 3:
			setVertexPoint(x+112, y+35, index+15);
			setVertexPoint(x+112, y+95, index+21);
			setVertexPoint(x+56, y+125, index+26);
			if(index == 7) {
				setVertexPoint(x, y+95, index+20);
				setVertexPoint(x, y+35, index+14);
			}
			break;
		case 4:
			setVertexPoint(x+112, y+35, index+22);
			setVertexPoint(x+112, y+95, index+27);
			setVertexPoint(x+56, y+125, index+31);
			if(index == 12) {
				setVertexPoint(x, y+95, index+26);
				setVertexPoint(x, y+35, index+21);
			}
			break;
		case 5:
			setVertexPoint(x+112, y+35, index+28);
			setVertexPoint(x+112, y+95, index+32);
			setVertexPoint(x+56, y+125, index+35);
			if(index == 16) {
				setVertexPoint(x, y+95, index+31);
				setVertexPoint(x, y+35, index+27);
			}
			break;
	}
}

function displayHexes(game) {
	game.append('<div id="hexes"><div class="row1"/><div class="row2"/><div class="row3"/><div class="row4"/><div class="row5"/></div>');
	var i=0;
	for(i=0; i < webui_client.context.hexes.length; i++) {
		var div = document.createElement('div');
		var resourceType = Enum.ResourceType[webui_client.context.hexes[i].type].toLowerCase();
		div.setAttribute('class', resourceType);
		if(resourceType != 'desert') {
			div.innerHTML = webui_client.context.hexes[i].number;
		}
		if(i >= 0 && i < 3) {		// First row
			addToRow(div, $('div.row1'), 1, i+1, i);
		} else if(i >= 3 && i < 7) {	// Second Row
			addToRow(div, $('div.row2'), 2, i-2, i);
		} else if(i >=7 && i < 12) {	// Third Row
			addToRow(div, $('div.row3'), 3, i-6, i);
		} else if(i >= 12 && i < 16) {	// Fourth Row
			addToRow(div, $('div.row4'), 4, i-11, i);
		} else if(i >= 16 && i < 19) {	// Fifth Row
			addToRow(div, $('div.row5'), 5, i-15, i);
		}	
	}
}

function displayDice(game) {
	game.append('<div id="dice"><div id="die1" class="dice"></div><div id="die2" class="dice"></div></div>');
	$('#die1').attr('style', 'background-image: url("images/dice'+webui_client.context.dice[0].val+'.png");');
	$('#die2').attr('style', 'background-image: url("images/dice'+webui_client.context.dice[1].val+'.png");');
}

function getClientPlayer() {
	var i=0;
	for(i=0; i<webui_client.context.players.length; i++) {
		var player = webui_client.context.players[i];
		if(player.token == webui_client.token) return player;
	}
	return undefined;
}

function getClientPlayerIndex() {
	var i=0;
	for(i=0; i<webui_client.context.players.length; i++) {
		var player = webui_client.context.players[i];
		if(player.token == webui_client.token) return i;
	}
	return undefined;
}

function getResourceCount(resourceLabel) {
	var i;
	var player = getClientPlayer();
	var count = 0;
	for(i=0; i < player.resources.length; i++) {
		if(Enum.ResourceType[player.resources[i]] == resourceLabel) count++;
	}
	return count;
}

function displayCards(game) {
	$('.card-grain').html(getResourceCount(Enum.ResourceType[0]));
	$('.card-sheep').html(getResourceCount(Enum.ResourceType[1]));
	$('.card-forest').html(getResourceCount(Enum.ResourceType[2]));
	$('.card-ore').html(getResourceCount(Enum.ResourceType[3]));
	$('.card-brick').html(getResourceCount(Enum.ResourceType[4]));
}

function displayBuildings(game) {
	var BUILDING_Y_OFFSET = 20; var BUILDING_X_OFFSET = 15;
	var i;
	for(i=0; i < webui_client.context.players.length; i++) {
		var player = webui_client.context.players[i];
		if(player && player.buildings && player.buildings.length > 0) {
			var j;
			for(j=0; j < player.buildings.length; j++) {
				var building = player.buildings[j];
				var vertex = webui_client.context.vertices[building.vertex];
				var img = document.createElement('img');
				img.setAttribute('style', 'top: '+(vertex.y-BUILDING_Y_OFFSET)+'; left: '+(vertex.x-BUILDING_X_OFFSET)+';');
				img.setAttribute('class', 'overlay');
				console.log('building.type='+building.type);
				var buildingType = Enum.BuildingType[building.type].toLowerCase();
				var color = playerColors[i]
				if(buildingType == 'city') {
					img.setAttribute('src', "images/city-"+color+".png"); 
				} else if(buildingType == 'settlement') {
					img.setAttribute('src', "images/settlement-"+color+".png"); 
				}
				game.append(img);
			}
		}
	}
}

function getXOffset(theta) {
	if(Math.abs((Math.abs(theta) - 90)) < 1) return -3;
	if(Math.abs((Math.abs(theta) - 28)) < 1) return 25;
	if(Math.abs((Math.abs(theta) - 30)) < 1) return 30;
	return 0;
}

function getYOffset(theta) {
	if(Math.abs((Math.abs(theta) - 90)) < 1) return 12;
	if(Math.abs((Math.abs(theta) - 28)) < 1) return -33;
	if(Math.abs((Math.abs(theta) - 30)) < 1) return 0;
	return 0;
}

function displayRoads() {
	for(i=0; i < webui_client.context.players.length; i++) {
		var player = webui_client.context.players[i];
		if(player && player.roads && player.roads.length > 0) {
			var j;
			for(j=0; j < player.roads.length; j++) {
				var road = player.roads[j];
				var edge = webui_client.context.edges[road.edge];
				var vertex1 = webui_client.context.vertices[edge.vertex1];
				var vertex2 = webui_client.context.vertices[edge.vertex2];
				if(!vertex1 || !vertex2) break;
				var img = document.createElement('img');
				var x,y,dx,dy;	
				var vertex1IsLeftmost = true;
				if(vertex2.x < vertex1.x) {
					vertex1IsLeftmost = false;
					x = vertex2.x; y = vertex2.y; 	
					dx = vertex1.x - vertex2.x;
					dy = vertex1.y - vertex2.y;
				} else {
					x = vertex1.x; y = vertex1.y;
					dx = vertex2.x - vertex1.x;
					dy = vertex2.y - vertex1.y;
				}
				var PI = 3.141;
				var theta = Math.atan(dy/dx) / PI * 180;
				var x_offset = getXOffset(theta);
				var y_offset = getYOffset(theta);
				var rotationDegrees = 90 + theta;
				img.setAttribute('style', 'top: '+(y+y_offset)+'; left: '+(x+x_offset)+'; -webkit-transform: rotate('+rotationDegrees+'deg);');
				img.setAttribute('class', 'overlay');
				var color = playerColors[i];
				img.setAttribute('src', "images/road-"+color+".png"); 
				$('#game').append(img);
			}
		}
	}
}

function sendMessage() {
	msg = $('.chatinput').val()
	args = msg.split("@")
	if(args.length == 2) 
		webui.server.send_message({msg: args[0], to_token_id:args[1]})
	else
		webui.server.send_message({msg: args[0]})
}

function appendMessage(msg) {
	$('.chatbox').append('<p id="message">' + msg + '</p>');
}

function displayPlayerList(players) {
  var html = '<p class="playerheader">who\'s online:</p>'
  for (var i = 0; i < players.length; i++) {
    html += '<p class="player">Player ' + players[i].token + '</p>';
  }
  $('.playerlist').html(html);
}

function enableActions() {
	actions_enabled = true;
	$('.input_action').removeClass('disabled_action');
	$('.input_action').addClass('enabled_action');
}

function disableActions() {
	actions_enabled = false;
	$('.input_action').addClass('disabled_action');
	$('.input_action').removeClass('enabled_action');
}

function enableCancelPurchase() {
	$('#cancelpurchase').removeClass('disabled_action');
	$('#cancelpurchase').addClass('enabled_action');
	disableActions();
}

function disableCancelPurchase() {
	$('#cancelpurchase').addClass('disabled_action');
	$('#cancelpurchase').removeClass('enabled_action');
	enableActions();
}

function displayTurnInfo(game) {
	var curPlayerIndex = webui_client.context.cur_player;
	// Display whose turn it is
	if(curPlayerIndex == getClientPlayerIndex()) {
		$('#turn').html('Your turn!');
		enableActions();
	} else {
		$('#turn').html('Player '+curPlayerIndex+'\'s turn');
		disableActions();
	}
}

function displayBoard() {
	var game = $('#game');
	game.empty();
	if(webui_client && webui_client.context) {
		displayHexes(game);
		displayDice(game);
		displayCards(game);
		displayRoads(game);
		displayBuildings(game);
		displayTurnInfo(game);
	}
}

function buyItem(item) {
	if(actions_enabled == false) return;
	enableCancelPurchase();
	// TODO: Check resources for the player, display error if not enough resources
	switch(item) {
		case 0:
			console.log("buying settlement")
			placing_settlement = true;
			break;
		case 1:
			console.log("buying city")
			placing_city = true;
			break;
		case 2:
			console.log("buying road")
			placing_road = true;
			break;
	}
}

function handleMouseMove(event) {
	var VERTICAL_THRESHOLD = 7;
	var HORIZONTAL_THRESHOLD = 7;
	var i=0;
	edgeIdx = getEdgeIdx(event.pageX, event.pageY);
	for(i=0; i < webui_client.context.vertices.length; i++) {
		var vertex = webui_client.context.vertices[i];
		if(Math.abs(vertex.x - event.pageX) < HORIZONTAL_THRESHOLD && Math.abs(vertex.y - event.pageY) < VERTICAL_THRESHOLD) {
			// TODO: handle hover
			return;
		}
		//TODO: detect edge hover. Use the isBetween function
		
	}
}

function getDistance(a,b,c,x,y) {
	return Math.abs(a*x+b*y+c)/(Math.sqrt(Math.pow(a,2) + Math.pow(b,2)))
}

function getPDisatance(x1,x2,y1,y2) {
	return Math.sqrt(Math.pow((x1-x2),2) + Math.pow((y1-y2),2))
}

function getSlope(x1,x2,y1,y2) {
	return (y1-y2) / (x1-x2); 
}

function between(x1,x2,x3) {
	return ((x3-x1) > 0) ^ ((x3-x2) > 0); 
}

function getIntercept(x1,x2,y1,y2) {
	return (y1*x2-y2*x1) / (x2-x1); 
}

function getEdgeIdx(x,y) {
	var THRESHOLD = 10
	for (var key in edge_to_vertext_map){
		vertices = edge_to_vertext_map[key]
		vertex1 = webui_client.context.vertices[vertices[0]]
		vertex2 = webui_client.context.vertices[vertices[1]]		                                         
		x1 = vertex1.x; y1 = vertex1.y
		x2 = vertex2.x; y2 = vertex2.y
		if(!between(y1,y2,y)){
			continue; 
		}
		if(x1==x2) {
			dist = Math.abs(x-x1)
		} else {
			if(!between(x1,x2,x)) continue; 
			m = getSlope(x1,x2,y1,y2);
			b = getIntercept(x1,x2,y1,y2);
			dist = getDistance(-m, 1, -b, x, y)
		}
		if(dist < THRESHOLD) {
//			log("edge idx: " + key + ", x" + x + ", y" + y + ", x1:" + x1 +
//					", y1:" + y1 + ", x2:" + x2 + ", y2:" + y2 + ", dist: " + dist)
//
			return key; 
		}
	}
	return -1
}

function getVertexIdx(x,y) {
	var VERTICAL_THRESHOLD = 7;
	var HORIZONTAL_THRESHOLD = 7;
	var i=0;
	for(i=0; i < webui_client.context.vertices.length; i++) {
		var vertex = webui_client.context.vertices[i];
		if(Math.abs(vertex.x - event.pageX) < HORIZONTAL_THRESHOLD && Math.abs(vertex.y - event.pageY) < VERTICAL_THRESHOLD) {
			alert('clicked on vertex '+i);
			return i; 
		}
	}
	return -1; 
}

function cancelPurchase() {
	if(actions_enabled == true) return;
	console.log('canceling purchase');
	//TODO: refund resources based on: placing_settlement, placing_city, or placing_road
	placing_road = false; placing_city = false; placing_road = false;
	disableCancelPurchase();
}

function endTurn() {
	if(actions_enabled == false) return;
	webui.end_turn();
}

function placeSettlement(idx) {
	if((placing_settlement == true  || placing_city == true)) {
		if(vertexHasBuilding(idx)) {
			// TODO: displayError("That vertex is full, stupid!");
		} else {
			// Add a settlement to player.buildings
			if(placing_settlement == true) {
				placeSettlementHelper(idx); 
				selected_vertex_id = idx;
			} else {
				console.log('adding city on vertex '+i);
				//TODO: make the server call to place city
				selected_vertex_id = idx;
			}
			placing_settlement = false;
			placing_city = false;
		}
		
		if (webui.mode == 'place_pieces') {
		  webui.place();
		}
		else if (webui.mode == 'my_turn') {
		  webui.buy();
		}
	}
}

function placeSettlementHelper(idx) {
	webui.server.buy_settlement({"vertex_id": idx}); 
}

function placeRoad(idx) {
	if(placing_road == true) {
		alert("edgeIdx: " + edgeIdx)
	}
}

function handleMouseUp(event) {
	vertexIdx = getVertexIdx(event.pageX, event.pageY)
	if(vertexIdx >= 0) {
		console.log("vertex idx: " + vertexIdx)
		placeSettlement(vertexIdx)
	} else {
		edgeIdx = getEdgeIdx(event.pageX, event.pageY);
		if(edgeIdx >= 0) {
			placeRoad(vertexIdx)
		}
	}
}

function edgeHasRoad(index) {
	if(!webui_client.context) return false;
	var players = webui_client.context.players;
	var i;
	for(i=0; i < players.length; i++) {
		var player = players[i];
		var j;
		for(j=0; j < player.roads.length; j++) {
			var road = player.roads[j];
			if(road.edge == index) return true;
		}
	}
	return false;
}

function vertexHasBuilding(index) {
	if(!webui_client.context) return false;
	var players = webui_client.context.players;
	var i;
	for(i=0; i < players.length; i++) {
		var player = players[i];
		var j;
		for(j=0; j < player.buildings.length; j++) {
			var building = player.buidlings[j];
			if(building.vertex == index) return true;
		}
	}
	return false;
}


// -Mouse-detection: 
//	-edges -- prereq: edges must have v1/v2 populated.  Detect if a point is nearly collinear between two vertices.
// -Opponent card/count
// Support and Display Harbors -- essentially an edge (or pair of adj vertices) with an associated trading condition
// -Development Cards
